package march;




import java.awt.Image;
import java.awt.image.BufferedImage;
import java.io.File;
import java.io.IOException;

import javax.imageio.ImageIO;

public class MarchableImage {
	
	private static final int MAX_MARCH_DIMENSION = 36;
	
	private File originalFile;
	
	private boolean[][] marchImage;
	private BufferedImage originalImage;
	
	private float averageWhite = -1;
	
	public MarchableImage(File original) throws IOException {
		this(original, -1);
	}
	
	public MarchableImage(File original, int cols) throws IOException {
		this.originalFile = original;
		createMarchSurface(original, cols);
	}
	

	public boolean[][] getMarchImage() {
		return marchImage;
	}
	
	
	public Image getOriginalImage() {
		return originalImage;
	}
	
	
	public void outputDebugFile() throws IOException {
		File debug = new File(originalFile.getParentFile(), "march-" + originalFile.getName() + ".png");
		
		int w = marchImage[0].length;
		int h = marchImage.length;
		
		int[] pixelArray = new int[marchImage.length * marchImage[0].length];
		
		int k = 0;
		for (int row = 0; row < marchImage.length; row++) {
			for (int col = 0; col < marchImage[0].length; col++) {
				
				if (marchImage[row][col]) {
					pixelArray[k] = 0xFF000000;
				} else {
					pixelArray[k] = 0xFFFFFFFF;
				}
				k++;
			}
		}
		
		 BufferedImage image = new BufferedImage(w, h, BufferedImage.TYPE_INT_ARGB);
		 image.setRGB(0, 0, w, h, pixelArray, 0, w);
//         WritableRaster raster = (WritableRaster) image.getData();
//         raster.setPixels(0,0,20,20,pixelArray);
//         
         ImageIO.write(image, "png", debug);
		
	}
	
	
	/*private void createMarchSurface(File f) throws IOException {
		createMarchSurface(f, -1);
	}*/
	
	private void createMarchSurface(File f, int forceWidth) throws IOException {
		
		System.out.println("Creating march surface...");
		
		originalImage = ImageIO.read(f);
		int width = originalImage.getWidth();
		int height = originalImage.getHeight();
		
		
		
		float scale;
		
		int marchWidth;
		if (forceWidth > 0) {
			marchWidth = forceWidth;
			scale = marchWidth * 1.0f / width;
		} else {
			int maxDim = Math.max(width, height);
			scale = MAX_MARCH_DIMENSION * 1.0f / maxDim;
			marchWidth = (int) (width * scale);
			if (marchWidth % 2 == 1) marchWidth++; // Force even number of columns
		}
		
		
		int marchHeight = (int) (height * scale);
		
		
		System.out.println("Scaling image...");
		Image march = originalImage.getScaledInstance(marchWidth, marchHeight, BufferedImage.SCALE_AREA_AVERAGING);
		
		BufferedImage b = new BufferedImage(marchWidth, marchHeight, BufferedImage.TYPE_INT_ARGB);
		
		b.getGraphics().drawImage(march, 0, 0, null);
		
		int[] rgbs = b.getRGB(0, 0, marchWidth, marchHeight, null, 0, marchWidth);
		
		marchImage = processRGB(rgbs, marchWidth, marchHeight);
		
		
	}

	private boolean[][] processRGB(int[] rgbs, int w, int h) {
		
		System.out.println("Average white...");
		averageWhite = averageWhite(rgbs, w, h);
		
		
		System.out.println("Bools...");
		boolean[][] bools = new boolean[h][w];
		
		for (int row = 0; row < h; row++) {
			for (int col = 0; col < w; col++) {
				bools[row][col] = isBlack(rgbs[col + row * w]);
			}
		}
		
		return bools;
	}
	
	private boolean isBlack(int rgb) {
		return lightness(rgb) < averageWhite;
	}
	
	private float averageWhite(int[] rgbs, int w, int h) {
		
		float total = 0;
		int speedup = 1;
		int number = w * h / (speedup * speedup);
		
		for (int row = 0; row < h; row += speedup) {
			for (int col = 0; col < w; col += speedup) {
				total += lightness(rgbs[col + row * w]);
			}
		}
		
		return total / number;
	}
	
	private float lightness(int rgb) {
		int redMask = 0xFF0000;
		int greenMask = 0x00FF00;
		int blueMask = 0x0000FF;
		
		int red = redMask & rgb;
		int blue = blueMask & rgb;
		int green = greenMask & rgb;
		
		return (red + blue + green) * 1.0f / 765;
	}

}
